﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using RLProject1.Model.AMEEWorld;
using Bettzueche.RLLibrary.Functions;

namespace RLProject1.UnitTest
{
    [TestClass]
    public class QFunktionTest
    {
        [TestMethod]
        public void QFunktion_GibThetaIndex() {
            // 2 Abschnitte, 2 Zielsektoren, 1+2 U-Werte
            float[] radienF = { 1.5f };
            int uIntervalle = 1;
            int sektoren = 2;
            Tiling tiling = new Tiling(uIntervalle, sektoren, radienF);
            //int thetaDim = tiling.Dimension * tiling.Aktionen; //18 * 2 = 36
            QFunktion testObj = new QFunktion(tiling);

            AMEEAction action0 = new AMEEAction{ Abschnittsnummer=0, SpurNummer=0, SektorNummer=0 };
            AMEEAction action1 = new AMEEAction{ Abschnittsnummer=1, SpurNummer=0, SektorNummer=1 };
            BumpinessFunction weltfunktion0 = (x, y) => 0.0; // uIndex= 0
            BumpinessFunction weltfunktion1 = (x, y) => 0.5; // uIndex= 1
            BumpinessFunction weltfunktion2 = (x, y) => 1.0; // uIndex= 2

            WorldImage state = new WorldImage(tiling,1,1, weltfunktion0);
            state.Zielrichtung = 0;
            state.Messe(.0, .0);
            int retVal = testObj.GibThetaIndex(state,action0)[0];
            int erwartet = 0;
            Assert.AreEqual<int>(erwartet, retVal, "Index erwartet: {0}. Erhalten: {1}.", erwartet, retVal);

            state.Zielrichtung = 1;
            retVal = testObj.GibThetaIndex(state, action0)[0];
            erwartet = 1;
            Assert.AreEqual<int>(erwartet, retVal, "Index erwartet: {0}. Erhalten: {1}.", erwartet, retVal);

            state = new WorldImage(tiling, 1, 1, weltfunktion2);
            state.Zielrichtung = 1;
            state.Messe(.0, .0);
            retVal = testObj.GibThetaIndex(state, action0)[0];
            erwartet = 17;
            Assert.AreEqual<int>(erwartet, retVal, "Index erwartet: {0}. Erhalten: {1}.", erwartet, retVal);

            state = new WorldImage(tiling, 1, 1, weltfunktion1);
            state.Zielrichtung = 0;
            state.Messe(.0, .0);
            retVal = testObj.GibThetaIndex(state, action1)[0];
            erwartet = 8 + 18;
            Assert.AreEqual<int>(erwartet, retVal, "Index erwartet: {0}. Erhalten: {1}.", erwartet, retVal);
        }

        [TestMethod]
        public void QFunktion_GetEstimates() {
            //Tiling
            float[] radienF = { 1.0f }; // 1 Spuren
            int uIntervalle = 1;
            int sektoren = 2; // O, W
            Tiling tiling = new Tiling(uIntervalle, sektoren, radienF);

            //QFunktion
            int thetaDim = tiling.Dimension * tiling.Aktionen; //2*3^2 * 2 = 18 * 2
            double thetaStart = 1.0; // => Q = 1
            QFunktion testObj = new QFunktion(thetaDim, thetaStart, tiling);

            //Aktionen
            AMEEAction action0 = new AMEEAction{ Abschnittsnummer=0, SpurNummer=0, SektorNummer=0 };
            AMEEAction action1 = new AMEEAction{ Abschnittsnummer=1, SpurNummer=0, SektorNummer=1 };

            //uFunktionen
            BumpinessFunction weltfunktion0 = (x, y) => x >= 0 ? 1.0 : 0.0; // uIndex= 2 für Ost, =0 für West
            BumpinessFunction weltfunktion1 = (x, y) => 0.5; // uIndex= 1
            BumpinessFunction weltfunktion2 = (x, y) => 1.0; // uIndex= 2

            //Zustand
            WorldImage state = new WorldImage(tiling, 1, 1, weltfunktion0);
            state.Zielrichtung = 0;
            state.Messe(.0, .0);

            double[] qWerte = testObj.GetEstimates(state);
            Assert.IsNotNull(qWerte, "Null-Array erhalten!");
            Assert.AreEqual<int>(2, qWerte.Length, "Nicht 2 Q-Werte erhalten sondern: ", qWerte.Length);
            Assert.AreEqual(1.0, qWerte[0], 0.0001, "Erster QWert erwartet: {0}. Ist aber: {1}", 1, qWerte[0].ToString("F4"));
            Assert.AreEqual(1.0, qWerte[1], 0.0001, "Erster QWert erwartet: {0}. Ist aber: {1}", 1, qWerte[0].ToString("F4"));


            testObj[state, action0] = 42.0;
            testObj[state, action1] = 142.0;

            qWerte = testObj.GetEstimates(state);
            Assert.IsNotNull(qWerte, "Null-Array erhalten!");
            Assert.AreEqual<int>(2, qWerte.Length, "Nicht 2 Q-Werte erhalten sondern: ", qWerte.Length);
            Assert.AreEqual(42.0, qWerte[0], 0.0001, "Erster QWert erwartet: {0}. Ist aber: {1}", 42, qWerte[0].ToString("F4"));
            Assert.AreEqual(142.0, qWerte[1], 0.0001, "Erster QWert erwartet: {0}. Ist aber: {1}", 142, qWerte[0].ToString("F4"));
        }
    }
}
